package com.atom.test.opengl

import android.annotation.SuppressLint
import android.graphics.Color
import android.graphics.PixelFormat
import android.graphics.PointF
import android.opengl.GLES30
import android.opengl.Matrix
import android.os.Bundle
import android.util.Log
import android.view.KeyEvent
import android.view.SurfaceHolder
import android.view.SurfaceView
import android.widget.SeekBar
import com.atom.module.lib.opengles.GLModule
import com.atom.module.lib.opengles.draw.Gl2dMesh
import com.atom.module.lib.opengles.draw.GlLine
import com.atom.module.lib.opengles.egl.EGLHelper
import com.atom.module.lib.opengles.egl.EGLWrapper
import com.atom.module.lib.opengles.ext.*
import com.atom.module.lib.opengles.shader.GlScene
import com.atom.module.lib.opengles.shader.GlSimpleProgram
import com.atom.module.logger.Logger
import com.atom.test.opengl.common.AbstractAppCompatActivity
import com.atom.test.opengl.utils.MatrixState

class ProjectMatrixActivity : AbstractAppCompatActivity() {

    private lateinit var surfaceView: SurfaceView
    private lateinit var wrapper: EGLWrapper
    private var flatProgram: GlSimpleProgram? = null

    private val scene = GlScene()
    private val drawable = Gl2dMesh().apply {
        this.setPoints(
            listOf(
                PointF(0F, 0F),//0
                PointF(0F, 1F),//1
                PointF(1F, 0F),//2
                PointF(0F, -1F),//3
                PointF(-1F, 0F),//4
                PointF(0.9F, 0.7F),//5
                PointF(0.7F, 0.9F),//6
                PointF(-0.9F, -0.7F),//7
                PointF(-0.7F, -0.9F),//8
                PointF(0.9F, -0.7F),//9
                PointF(0.7F, -0.9F),//10
                PointF(-0.9F, 0.7F),//11
                PointF(-0.7F, 0.9F)//12
            )
        )
    }
    private val line = GlLine().apply {
        this.setPoints(
            listOf(
                PointF(0F, 0F),//0
                PointF(0F, 1F),//1
                PointF(0F, 0F),//0
                PointF(1F, 0F)//2
            )
        )
    }

    @SuppressLint("ClickableViewAccessibility")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_matrix_project)
        setTitle("ViewMatrixActivity")
        view(R.id.surface_view, PickView<SurfaceView> {
            surfaceView = it
            surfaceView.setZOrderOnTop(true)
            surfaceView.holder.setFormat(PixelFormat.RGBA_8888)
            surfaceView.holder.addCallback(object : SurfaceHolder.Callback {
                override fun surfaceCreated(holder: SurfaceHolder) {
                    Log.e("SHAPES", "CREATED." + Thread.currentThread().name)
                    onSurfaceCreated(holder)
                }

                override fun surfaceChanged(
                    holder: SurfaceHolder,
                    format: Int,
                    width: Int,
                    height: Int
                ) {

                }

                override fun surfaceDestroyed(holder: SurfaceHolder) {
                    onSurfaceDestroyed()
                }
            })
        })

        view(R.id.seek_width, PickView<SeekBar> {
            it.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
                override fun onProgressChanged(
                    seekBar: SeekBar?,
                    progress: Int,
                    fromUser: Boolean
                ) {

                }

                override fun onStartTrackingTouch(seekBar: SeekBar?) {
//                    val matrix4 = Matrix4()
//                    val toPerspectiveProjection = matrix4.setToPerspectiveProjection(
//                        scene.viewportWidth.toDouble(), scene.viewportHeight.toDouble(),
//                        seekBar!!.progress.toDouble(),
//                        1.0, 2.0
//                    )
//                    LogUtils.e(toPerspectiveProjection)
                }

                override fun onStopTrackingTouch(seekBar: SeekBar?) {
                    Matrix.frustumM(scene.projectionMatrix, 0, -1f, 1f, -1f, 1f, 1f, 3f)
                    draw()
                }
            })
        })

    }

    private fun onSurfaceCreated(holder: SurfaceHolder) {
        wrapper = EGLHelper.initDisplay()
        wrapper.createGLESWithSurface(surface = holder.surface!!)
        flatProgram = GlSimpleProgram()
    }

    private fun onSurfaceDestroyed() {
        flatProgram?.release()
        flatProgram = null
        wrapper.release()
    }

    private fun draw() {
        Log.w("SHAPES", "drawing.")
        GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT)
        // Draw the circle.
        flatProgram?.setColor(Color.RED)
        scene.draw(flatProgram!!, drawable)
        flatProgram?.setColor(Color.GREEN)
        scene.draw(flatProgram!!, line)
        // Publish.
        wrapper.swapBuffers()
    }

    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
        if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
            Log.e(GLModule.TAG, "Model Matrix ${drawable.modelMatrix.print()}")
        } else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
            Logger.e(MatrixState.printMatrix(drawable.modelMatrix))
            draw()
        }

        return super.onKeyDown(keyCode, event)
    }

    override fun onDestroy() {
        onSurfaceDestroyed()
        super.onDestroy()
    }
}